/*
 * StalkerView.java
 */
package stalker;

import java.awt.Dimension;
import java.io.FileNotFoundException;
import org.jdesktop.application.Action;
import org.jdesktop.application.ResourceMap;
import org.jdesktop.application.SingleFrameApplication;
import org.jdesktop.application.FrameView;
import org.jdesktop.application.TaskMonitor;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.InetAddress;
import java.net.Socket;
import javax.swing.Timer;
import javax.swing.Icon;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JOptionPane;

/**
 * The application's main frame.
 */
public class StalkerView extends FrameView {

    private static String DefaultDNSip;
    private static int DefaultDNSport;
    public static String ClientIp;
    public static int ClientPort;
    public static int _port;
    private static String Mynick;
    public Mensagem MsgToServer;
    public Mensagem MsgfromClient;
    private byte[] ByteBuffer;
    public static String NickClient;
    private final static String newline = "\n";

    public StalkerView(SingleFrameApplication app, String ipDefault, int portaDefault, String nick, int porta_Client) throws FileNotFoundException, Exception {
        super(app);
        DefaultDNSip = ipDefault;
        DefaultDNSport = portaDefault;
        initComponents();
        Mynick = nick;
        lblNick.setText(nick);
        _port = porta_Client;
        
        
        final JFrame frame = this.getFrame();
        frame.setSize(new Dimension(800, 1200));        
        frame.setResizable(false);
        frame.setTitle(Mynick + " - chat");
        frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
        frame.addWindowListener(new WindowAdapter() {

            @Override
            public void windowClosing(WindowEvent we) {
                if (!btnFim.isEnabled()) {
                    int answer = JOptionPane.showConfirmDialog(null,
                            "Deseja realmente sair do chat? Você será desconectado do Servidor de DNS.",
                            "Fechando o Chat...",
                            JOptionPane.YES_NO_OPTION);

                    if (answer == 1) {
                        return;
                    } else {
                        SendMessageToDNS(2, Mynick);
                        System.exit(0);
                    }
                    return;
                }
            }
        });

        // status bar initialization - message timeout, idle icon and busy animation, etc
        ResourceMap resourceMap = getResourceMap();
        int messageTimeout = resourceMap.getInteger("StatusBar.messageTimeout");
        messageTimer = new Timer(messageTimeout, new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                statusMessageLabel.setText("");
            }
        });
        messageTimer.setRepeats(false);
        int busyAnimationRate = resourceMap.getInteger("StatusBar.busyAnimationRate");
        for (int i = 0; i < busyIcons.length; i++) {
            busyIcons[i] = resourceMap.getIcon("StatusBar.busyIcons[" + i + "]");
        }
        busyIconTimer = new Timer(busyAnimationRate, new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                busyIconIndex = (busyIconIndex + 1) % busyIcons.length;
                statusAnimationLabel.setIcon(busyIcons[busyIconIndex]);
            }
        });
        idleIcon = resourceMap.getIcon("StatusBar.idleIcon");
        statusAnimationLabel.setIcon(idleIcon);
        progressBar.setVisible(false);

        // connecting action tasks to status bar via TaskMonitor
        TaskMonitor taskMonitor = new TaskMonitor(getApplication().getContext());
        taskMonitor.addPropertyChangeListener(new java.beans.PropertyChangeListener() {

            public void propertyChange(java.beans.PropertyChangeEvent evt) {
                String propertyName = evt.getPropertyName();
                if ("started".equals(propertyName)) {
                    if (!busyIconTimer.isRunning()) {
                        statusAnimationLabel.setIcon(busyIcons[0]);
                        busyIconIndex = 0;
                        busyIconTimer.start();
                    }
                    progressBar.setVisible(true);
                    progressBar.setIndeterminate(true);
                } else if ("done".equals(propertyName)) {
                    busyIconTimer.stop();
                    statusAnimationLabel.setIcon(idleIcon);
                    progressBar.setVisible(false);
                    progressBar.setValue(0);
                } else if ("message".equals(propertyName)) {
                    String text = (String) (evt.getNewValue());
                    statusMessageLabel.setText((text == null) ? "" : text);
                    messageTimer.restart();
                } else if ("progress".equals(propertyName)) {
                    int value = (Integer) (evt.getNewValue());
                    progressBar.setVisible(true);
                    progressBar.setIndeterminate(false);
                    progressBar.setValue(value);
                }
            }
        });



        //Criando Socket em thread separada para receber mensagens
        CreateMessageRcv(_port);
    }

    @Action
    public void showAboutBox() {
        if (aboutBox == null) {
            JFrame mainFrame = StalkerApp.getApplication().getMainFrame();
            aboutBox = new StalkerAboutBox(mainFrame);
            aboutBox.setLocationRelativeTo(mainFrame);
        }
        StalkerApp.getApplication().show(aboutBox);
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        mainPanel = new javax.swing.JPanel();
        jScrollPane1 = new javax.swing.JScrollPane();
        txtChatArea = new javax.swing.JTextArea();
        btnEnviar = new javax.swing.JButton();
        btnConectar = new javax.swing.JButton();
        txtNome = new javax.swing.JTextField();
        jLabel1 = new javax.swing.JLabel();
        jScrollPane2 = new javax.swing.JScrollPane();
        txtMessage = new javax.swing.JTextArea();
        lblNick = new javax.swing.JLabel();
        btnFim = new javax.swing.JButton();
        statusPanel = new javax.swing.JPanel();
        javax.swing.JSeparator statusPanelSeparator = new javax.swing.JSeparator();
        statusMessageLabel = new javax.swing.JLabel();
        statusAnimationLabel = new javax.swing.JLabel();
        progressBar = new javax.swing.JProgressBar();

        mainPanel.setName("mainPanel"); // NOI18N

        jScrollPane1.setName("jScrollPane1"); // NOI18N

        txtChatArea.setColumns(20);
        txtChatArea.setEditable(false);
        txtChatArea.setRows(5);
        txtChatArea.setName("txtChatArea"); // NOI18N
        jScrollPane1.setViewportView(txtChatArea);

        org.jdesktop.application.ResourceMap resourceMap = org.jdesktop.application.Application.getInstance(stalker.StalkerApp.class).getContext().getResourceMap(StalkerView.class);
        btnEnviar.setText(resourceMap.getString("btnEnviar.text")); // NOI18N
        btnEnviar.setEnabled(false);
        btnEnviar.setName("btnEnviar"); // NOI18N
        btnEnviar.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnEnviarActionPerformed(evt);
            }
        });

        btnConectar.setText(resourceMap.getString("btnConectar.text")); // NOI18N
        btnConectar.setName("btnConectar"); // NOI18N
        btnConectar.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnConectarActionPerformed(evt);
            }
        });

        txtNome.setText(resourceMap.getString("txtNome.text")); // NOI18N
        txtNome.setName("txtNome"); // NOI18N

        jLabel1.setText(resourceMap.getString("jLabel1.text")); // NOI18N
        jLabel1.setName("jLabel1"); // NOI18N

        jScrollPane2.setAutoscrolls(true);
        jScrollPane2.setName("jScrollPane2"); // NOI18N

        txtMessage.setColumns(20);
        txtMessage.setRows(5);
        txtMessage.setEnabled(false);
        txtMessage.setName("txtMessage"); // NOI18N
        txtMessage.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyPressed(java.awt.event.KeyEvent evt) {
                txtMessageKeyPressed(evt);
            }
            public void keyReleased(java.awt.event.KeyEvent evt) {
                txtMessageKeyReleased(evt);
            }
        });
        jScrollPane2.setViewportView(txtMessage);

        lblNick.setFont(resourceMap.getFont("lblNick.font")); // NOI18N
        lblNick.setForeground(resourceMap.getColor("lblNick.foreground")); // NOI18N
        lblNick.setText(resourceMap.getString("lblNick.text")); // NOI18N
        lblNick.setName("lblNick"); // NOI18N

        btnFim.setText(resourceMap.getString("btnFim.text")); // NOI18N
        btnFim.setEnabled(false);
        btnFim.setName("btnFim"); // NOI18N
        btnFim.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnFimActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout mainPanelLayout = new javax.swing.GroupLayout(mainPanel);
        mainPanel.setLayout(mainPanelLayout);
        mainPanelLayout.setHorizontalGroup(
            mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, mainPanelLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 703, Short.MAX_VALUE)
                    .addGroup(mainPanelLayout.createSequentialGroup()
                        .addComponent(lblNick, javax.swing.GroupLayout.DEFAULT_SIZE, 295, Short.MAX_VALUE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jLabel1)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(txtNome, javax.swing.GroupLayout.PREFERRED_SIZE, 169, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(btnConectar)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(btnFim))
                    .addGroup(mainPanelLayout.createSequentialGroup()
                        .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 620, Short.MAX_VALUE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(btnEnviar, javax.swing.GroupLayout.PREFERRED_SIZE, 73, javax.swing.GroupLayout.PREFERRED_SIZE)))
                .addContainerGap())
        );
        mainPanelLayout.setVerticalGroup(
            mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(mainPanelLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(lblNick)
                    .addComponent(txtNome, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(btnConectar)
                    .addComponent(jLabel1)
                    .addComponent(btnFim))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 203, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 94, Short.MAX_VALUE)
                    .addComponent(btnEnviar, javax.swing.GroupLayout.DEFAULT_SIZE, 94, Short.MAX_VALUE))
                .addGap(31, 31, 31))
        );

        jLabel1.getAccessibleContext().setAccessibleName(resourceMap.getString("jLabel1.AccessibleContext.accessibleName")); // NOI18N
        lblNick.getAccessibleContext().setAccessibleName(resourceMap.getString("lblNick.AccessibleContext.accessibleName")); // NOI18N

        statusPanel.setName("statusPanel"); // NOI18N

        statusPanelSeparator.setName("statusPanelSeparator"); // NOI18N

        statusMessageLabel.setName("statusMessageLabel"); // NOI18N

        statusAnimationLabel.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
        statusAnimationLabel.setName("statusAnimationLabel"); // NOI18N

        progressBar.setName("progressBar"); // NOI18N

        javax.swing.GroupLayout statusPanelLayout = new javax.swing.GroupLayout(statusPanel);
        statusPanel.setLayout(statusPanelLayout);
        statusPanelLayout.setHorizontalGroup(
            statusPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(statusPanelSeparator, javax.swing.GroupLayout.DEFAULT_SIZE, 723, Short.MAX_VALUE)
            .addGroup(statusPanelLayout.createSequentialGroup()
                .addContainerGap()
                .addComponent(statusMessageLabel)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 703, Short.MAX_VALUE)
                .addComponent(statusAnimationLabel)
                .addContainerGap())
            .addGroup(statusPanelLayout.createSequentialGroup()
                .addGap(143, 143, 143)
                .addComponent(progressBar, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap(430, Short.MAX_VALUE))
        );
        statusPanelLayout.setVerticalGroup(
            statusPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(statusPanelLayout.createSequentialGroup()
                .addComponent(statusPanelSeparator, javax.swing.GroupLayout.PREFERRED_SIZE, 2, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addGroup(statusPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                    .addGroup(statusPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                        .addComponent(statusMessageLabel)
                        .addComponent(statusAnimationLabel))
                    .addComponent(progressBar, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addGap(3, 3, 3))
        );

        setComponent(mainPanel);
        setStatusBar(statusPanel);
    }// </editor-fold>//GEN-END:initComponents

    private void CreateMessageRcv(int sockPort) {
        try {
            ClientMessageRcv clRcv = new ClientMessageRcv(this, sockPort);
            clRcv.execute();
        } catch (Exception e) {
            System.out.println(e + "Erro no receptor");
        }
    }

    private void btnConectarActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnConectarActionPerformed

        if (txtNome.getText().trim().equals("")) {
            //CORRIGIR: VER COMO FAZ ALERTA PARA FRAMEVIEW
            JOptionPane.showMessageDialog(null,"Favor preencha o nick do contato que deseja conversar.","Erro",JOptionPane.ERROR_MESSAGE);
            return;
        }else if (txtNome.getText().trim().equals(lblNick.getText())) {
            JOptionPane.showMessageDialog(null,"Você não pode conversar consigo mesmo.","Erro",JOptionPane.ERROR_MESSAGE);
            return;
        }

        try {
            Socket sock = new Socket(DefaultDNSip, DefaultDNSport); // cria socket

            ObjectOutputStream out = new ObjectOutputStream(sock.getOutputStream());
            ObjectInputStream in = new ObjectInputStream(sock.getInputStream());
            // cria a estrutura de dados a ser enviada

            MsgToServer = new Mensagem();
            MsgToServer.setCdTransacao((byte) 4);
            MsgToServer.setIp(MsgToServer.ipToInt(InetAddress.getLocalHost().getHostAddress()));
            MsgToServer.setPorta((short) 0);
            MsgToServer.setTexto(lblNick.getText() + " " + txtNome.getText());

            out.write(MsgToServer.convertToByteBuffer());
            out.flush();

            ByteBuffer = new byte[1024];
            in.read(ByteBuffer);

            MsgfromClient = new Mensagem();
            MsgfromClient.convertToClass(ByteBuffer);

            if (MsgfromClient.getTexto().startsWith("ON")) {
                ClientIp = MsgfromClient.intToIp(MsgfromClient.getIp());
                ClientPort = MsgfromClient.getPorta();

                NickClient = txtNome.getText();
                txtChatArea.append("Você está conectado com: " + NickClient + "\nIp: " + ClientIp + "\n\n");
                SendMessageToServer(6, lblNick.getText());

                txtNome.setEnabled(false);
                btnConectar.setEnabled(false);                
                txtMessage.setEnabled(true);
                btnEnviar.setEnabled(true);
                btnFim.setEnabled(true);
            } else if (MsgfromClient.getTexto().startsWith("OCUPADO")) {
                txtChatArea.append("Usuário " + txtNome.getText() + " está OCUPADDO no momento, favor tente mais tarde.\n");
            } else if (MsgfromClient.getTexto().startsWith("OFF")) {
                txtChatArea.append("Usuário " + txtNome.getText() + " não está conectado no momento, favor tente mais tarde.\n");
            } else {
                txtChatArea.append(MsgfromClient.getTexto() + ".\n");
            }


            in.close();
            out.close();
            sock.close();

        } catch (Exception ex) {
            txtChatArea.setText(ex.getMessage());
        }
    }//GEN-LAST:event_btnConectarActionPerformed

    private void btnEnviarActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnEnviarActionPerformed
        EnviaConversa();
        txtMessage.setCaretPosition(0);
        txtMessage.setText("");
    }//GEN-LAST:event_btnEnviarActionPerformed

    private void btnFimActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnFimActionPerformed
        try {
            SendMessageToServer(8, ""); //avisa ao outro cliente que a conversa encerrou
            SendMessageToDNS(5, Mynick + " " + NickClient); //avisa ao DNS que a conversa encerrou
            txtChatArea.append("Conversa com " + txtNome.getText() + " foi encerrada." + newline);


            txtNome.setEnabled(true);
            btnConectar.setEnabled(true);
            txtNome.setText("");
            txtMessage.setEnabled(false);
            btnEnviar.setEnabled(false);
            btnFim.setEnabled(false);
        } catch (Exception ex) {
            txtChatArea.setText(ex.getMessage());
        }
    }//GEN-LAST:event_btnFimActionPerformed

    private void txtMessageKeyPressed(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_txtMessageKeyPressed
        //if (btnEnviar.isEnabled() && !txtMessage.getText().trim().equals("")) {
            if (evt.getKeyCode() == KeyEvent.VK_ENTER) {
                EnviaConversa();
            }
        //}
    }//GEN-LAST:event_txtMessageKeyPressed

    private void txtMessageKeyReleased(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_txtMessageKeyReleased
            if (evt.getKeyCode() == KeyEvent.VK_ENTER) {
                txtMessage.setCaretPosition(0);
                txtMessage.setText("");
            }
    }//GEN-LAST:event_txtMessageKeyReleased

    // Variables declaration - do not modify//GEN-BEGIN:variables
    public javax.swing.JButton btnConectar;
    public javax.swing.JButton btnEnviar;
    public javax.swing.JButton btnFim;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JLabel lblNick;
    private javax.swing.JPanel mainPanel;
    private javax.swing.JProgressBar progressBar;
    private javax.swing.JLabel statusAnimationLabel;
    private javax.swing.JLabel statusMessageLabel;
    private javax.swing.JPanel statusPanel;
    public javax.swing.JTextArea txtChatArea;
    public javax.swing.JTextArea txtMessage;
    public javax.swing.JTextField txtNome;
    // End of variables declaration//GEN-END:variables
    private final Timer messageTimer;
    private final Timer busyIconTimer;
    private final Icon idleIcon;
    private final Icon[] busyIcons = new Icon[15];
    private int busyIconIndex = 0;
    private JDialog aboutBox;

    private void SendMessageToServer(int cdTransacao, /*int ip, int porta,*/ String text) {
        try {

            Socket sock = new Socket(ClientIp, ClientPort);
            ObjectOutputStream out = new ObjectOutputStream(sock.getOutputStream());
            //ObjectInputStream in = new ObjectInputStream(sock.getInputStream());

            MsgToServer = new Mensagem();
            MsgToServer.setCdTransacao((byte) cdTransacao);
            MsgToServer.setIp(MsgToServer.ipToInt(InetAddress.getLocalHost().getHostAddress()));
            MsgToServer.setPorta((short) _port);
            MsgToServer.setTexto(text);


            out.write(MsgToServer.convertToByteBuffer());
            out.flush();


            //ByteBuffer = new byte[1024];
            //in.read(ByteBuffer);
            //MsgfromClient.convertToClass(ByteBuffer);

            //in.close();
            out.close();
            sock.close();

        } catch (Exception ex) {
            txtChatArea.append("\n\n\n" + ex.getMessage());
        }
    }

    private void SendMessageToDNS(int cdTransacao, /*int ip, int porta,*/ String text) {
        try {

            Socket sock = new Socket(DefaultDNSip, DefaultDNSport);
            ObjectOutputStream out = new ObjectOutputStream(sock.getOutputStream());
            ObjectInputStream in = new ObjectInputStream(sock.getInputStream());

            MsgToServer = new Mensagem();
            MsgToServer.setCdTransacao((byte) cdTransacao);
            MsgToServer.setIp(MsgToServer.ipToInt(DefaultDNSip));
            MsgToServer.setPorta((short) DefaultDNSport);
            MsgToServer.setTexto(text);

            out.write(MsgToServer.convertToByteBuffer());
            out.flush();


            ByteBuffer = new byte[1024];
            in.read(ByteBuffer);
            
            MsgfromClient = new Mensagem();
            MsgfromClient.convertToClass(ByteBuffer);

            in.close();
            out.close();
            sock.close();

        } catch (Exception ex) {
            txtChatArea.append("\n\n\n" + ex.getMessage());
        }
    }

    private void EnviaConversa() {
        try {
            SendMessageToServer(7, txtMessage.getText().trim());
            txtChatArea.append(lblNick.getText() + " diz: " + newline + txtMessage.getText() + newline);
            txtChatArea.setCaretPosition(txtChatArea.getText().length());            
        } catch (Exception ex) {
            txtChatArea.setText(ex.getMessage());
        }
    }
}
